package cn.stylefeng.guns.modular.dailyandrealtimeprices.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.modular.dailyandrealtimeprices.entity.QyuanPowerSdPrices;
import cn.stylefeng.guns.modular.dailyandrealtimeprices.enums.QyuanPowerSdPricesExceptionEnum;
import cn.stylefeng.guns.modular.dailyandrealtimeprices.mapper.QyuanPowerSdPricesMapper;
import cn.stylefeng.guns.modular.dailyandrealtimeprices.pojo.request.QyuanPowerSdPricesRequest;
import cn.stylefeng.guns.modular.dailyandrealtimeprices.service.QyuanPowerSdPricesService24;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 24时电价表，记录每天96个时间点的不同电价情况(日前和实时)业务实现层
 *
 * @author 我是谭先生🐻
 * @date 2025/03/17 11:36
 */
@Service
public class QyuanPowerSdPricesServiceImpl24 extends ServiceImpl<QyuanPowerSdPricesMapper, QyuanPowerSdPrices> implements QyuanPowerSdPricesService24 {


    @Override
    public PageResult<QyuanPowerSdPrices> findPage24(QyuanPowerSdPricesRequest request) {
        // 1. 分页参数初始化
        int pageNo = request.getPageNo() != null ? request.getPageNo() : 1;
        int pageSize = request.getPageSize() != null ? request.getPageSize() : 24;

        // 2. 计算原始数据分页参数
        int rawDataPageSize = pageSize * 4; // 每组4条原始数据
        Page<QyuanPowerSdPrices> rawPage = new Page<>(pageNo, rawDataPageSize);

        // 3. 执行原始数据分页查询（包含总数统计）
        LambdaQueryWrapper<QyuanPowerSdPrices> wrapper = createWrapper(request);
        wrapper.orderByAsc(QyuanPowerSdPrices::getUsageDate, QyuanPowerSdPrices::getTimePoint);
        this.page(rawPage, wrapper);

        // 4. 计算处理后数据的总数（每组4条原始数据对应1条结果）
        int totalProcessed = (int) Math.ceil(rawPage.getTotal() / 4.0);

        // 5. 处理当前页的原始数据
        List<QyuanPowerSdPrices> processedData = processData(rawPage.getRecords());

        // 6. 构建最终分页结果
        Page<QyuanPowerSdPrices> resultPage = new Page<>(pageNo, pageSize, totalProcessed);
        resultPage.setRecords(processedData);
        return PageResultFactory.createPageResult(resultPage);
    }

    // 列表查询方法
    @Override
    public List<QyuanPowerSdPrices> findList24(QyuanPowerSdPricesRequest request) {
        // 获取原始数据
        LambdaQueryWrapper<QyuanPowerSdPrices> wrapper = createWrapper(request);
        wrapper.orderByAsc(QyuanPowerSdPrices::getUsageDate, QyuanPowerSdPrices::getTimePoint);
        List<QyuanPowerSdPrices> rawData = this.list(wrapper);

        // 调用统一处理方法
        return processData(rawData);
    }

    /**
     * 获取信息
     *
     * @author 我是谭先生🐻
     * @date 2025/03/17 11:36
     */
    private QyuanPowerSdPrices queryQyuanPowerSdPrices(QyuanPowerSdPricesRequest qyuanPowerSdPricesRequest) {
        QyuanPowerSdPrices qyuanPowerSdPrices = this.getById(qyuanPowerSdPricesRequest.getId());
        if (ObjectUtil.isEmpty(qyuanPowerSdPrices)) {
            throw new ServiceException(QyuanPowerSdPricesExceptionEnum.QYUAN_POWER_SD_PRICES_NOT_EXISTED);
        }
        return qyuanPowerSdPrices;
    }

    /**
     * 创建查询wrapper
     *
     * @author 我是谭先生🐻
     * @date 2025/03/17 11:36
     */
    private LambdaQueryWrapper<QyuanPowerSdPrices> createWrapper(QyuanPowerSdPricesRequest qyuanPowerSdPricesRequest) {
        LambdaQueryWrapper<QyuanPowerSdPrices> queryWrapper = new LambdaQueryWrapper<>();

        Integer id = qyuanPowerSdPricesRequest.getId();
        String usageDate = qyuanPowerSdPricesRequest.getUsageDate();
        Integer timePoint = qyuanPowerSdPricesRequest.getTimePoint();
        String timeSlot = qyuanPowerSdPricesRequest.getTimeSlot();
        BigDecimal dayaheadPrice = qyuanPowerSdPricesRequest.getDayaheadPrice();
        BigDecimal realtimePrice = qyuanPowerSdPricesRequest.getRealtimePrice();
        String createdAt = qyuanPowerSdPricesRequest.getCreateTime();
        String updatedAt = qyuanPowerSdPricesRequest.getUpdateTime();

        queryWrapper.eq(ObjectUtil.isNotNull(id), QyuanPowerSdPrices::getId, id);
        queryWrapper.eq(ObjectUtil.isNotNull(usageDate), QyuanPowerSdPrices::getUsageDate, usageDate);
        queryWrapper.eq(ObjectUtil.isNotNull(timePoint), QyuanPowerSdPrices::getTimePoint, timePoint);
        queryWrapper.like(ObjectUtil.isNotEmpty(timeSlot), QyuanPowerSdPrices::getTimeSlot, timeSlot);
        queryWrapper.eq(ObjectUtil.isNotNull(dayaheadPrice), QyuanPowerSdPrices::getDayaheadPrice, dayaheadPrice);
        queryWrapper.eq(ObjectUtil.isNotNull(realtimePrice), QyuanPowerSdPrices::getRealtimePrice, realtimePrice);
        queryWrapper.eq(ObjectUtil.isNotNull(createdAt), QyuanPowerSdPrices::getCreateTime, createdAt);
        queryWrapper.eq(ObjectUtil.isNotNull(updatedAt), QyuanPowerSdPrices::getUpdateTime, updatedAt);

        return queryWrapper;
    }


    /**
     * 统一的数据处理方法（包含分组、聚合计算、结果构建）
     *
     * @param rawData 原始数据列表
     * @return 处理后的聚合数据列表
     */
    private List<QyuanPowerSdPrices> processData(List<QyuanPowerSdPrices> rawData) {
        List<QyuanPowerSdPrices> result = new ArrayList<>();

        // 按日期和时段分组
        Map<LocalDate, Map<Integer, List<QyuanPowerSdPrices>>> groupedData = new LinkedHashMap<>();
        for (QyuanPowerSdPrices data : rawData) {
            try {
                // 1. 空值检查
                if (data.getUsageDate() == null) {
                    log.warn("数据异常：UsageDate为空，记录ID={}");
                    continue;
                }

                // 2. 转换日期和时段
                LocalDate date = data.getUsageDate().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate();
                int hourPeriod = (data.getTimePoint() - 1) / 4 + 1;  // 1-96转1-24

                // 3. 分组存储
                groupedData
                        .computeIfAbsent(date, k -> new LinkedHashMap<>())
                        .computeIfAbsent(hourPeriod, k -> new ArrayList<>())
                        .add(data);
            } catch (Exception e) {
                log.error("数据处理异常，记录ID={}：{}");
            }
        }

        // 处理分组数据
        groupedData.forEach((date, hourMap) -> {
            hourMap.forEach((hourPeriod, group) -> {
                // 4. 检查数据完整性
                if (group.size() != 4) {
                    log.warn("数据不完整：日期={} 时段={} 实际数据量={}");
                    return;
                }

                try {
                    // 5. 计算平均值
                    // 处理日前电价平均值
                    List<BigDecimal> dayaheadPrices = group.stream()
                            .map(d -> d.getDayaheadPrice())
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

                    BigDecimal dayAheadAvg = null;
                    if (!dayaheadPrices.isEmpty()) {
                        BigDecimal sum = dayaheadPrices.stream()
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        dayAheadAvg = sum.divide(
                                new BigDecimal(dayaheadPrices.size()), // 根据实际有效数据量计算
                                4,
                                RoundingMode.HALF_UP
                        );
                    }

                    // 处理实时电价平均值（同理）
                    List<BigDecimal> realtimePrices = group.stream()
                            .map(d -> d.getRealtimePrice())
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

                    BigDecimal realtimeAvg = null;
                    if (!realtimePrices.isEmpty()) {
                        BigDecimal sum = realtimePrices.stream()
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        realtimeAvg = sum.divide(
                                new BigDecimal(realtimePrices.size()),
                                4,
                                RoundingMode.HALF_UP
                        );
                    }

                    // 6. 构建结果对象
                    QyuanPowerSdPrices processed = new QyuanPowerSdPrices();
                    QyuanPowerSdPrices first = group.get(0);

                    processed.setId(first.getId());
                    processed.setUsageDate(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
                    processed.setTimeSlot(String.format("%02d:00", hourPeriod));
                    processed.setTimePoint(hourPeriod);
                    processed.setDayaheadPrice(dayAheadAvg);
                    processed.setRealtimePrice(realtimeAvg);
                    processed.setCreateTime(first.getCreateTime());
                    processed.setUpdateTime(group.get(3).getUpdateTime());

                    result.add(processed);
                } catch (Exception e) {
                    log.error("聚合计算异常：日期={} 时段={}，错误：{}");
                }
            });
        });

        return result;
    }

}